package com.andnnl.list;

import com.google.common.collect.Lists;
import org.apache.commons.collections.ListUtils;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.ToIntFunction;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * Created by chenss on 2021/4/13.
 */
public class ListsPartitionTest1 {
    public static void main(String[] args) {
//        test1();
//        test2();
//        test3();
//        test4();
//        final List<Integer> list = Arrays.asList(3, 4, 5, 6, 7, 1, 2, 8, 5, 5, 9, 5, 6, 10, 11, 12,23,20,2,12,5,5,22);
//        Map<Integer, List<Integer>> map = partitionList(list, 20, t -> t);
//        System.out.println(map);

    }


    /**
     * 按数量统计值分割，顺序累计少于等于一个固定值时，分割成多个列表</br>
     * 如：按顺序分组，每组的和小于等于20</br>
     *      Map<Integer, List<Integer>> map = partitionList(list, 20, t ->  t);</br>
     * 列表：Arrays.asList(3, 4, 5, 6, 7, 1, 2, 8, 5, 5, 9, 5, 6, 10, 11, 12);</br>
     * 返回：{0=[3, 4, 5, 6], 1=[7, 1, 2, 8], 2=[5, 5, 9], 3=[5, 6], 4=[10], 5=[11], 6=[12]}</br>
     *
     * @param list 列表
     * @param size 最大数量
     * @param intFun 返回数量函数
     * @param <T>
     * @return Map
     */
    public static <T> Map<Integer, List<T>> partitionList(List<T> list, int size, ToIntFunction<T> intFun) {
        final AtomicInteger counter = new AtomicInteger();
        final AtomicInteger g = new AtomicInteger();
        Map<Integer, List<T>> map = list.stream()
                .collect(Collectors.groupingBy((T it) -> {
                    int r = intFun.applyAsInt(it);
                    if (counter.get() + r <= size) {
                        counter.addAndGet(r);
                        return g.get();
                    } else {
                        counter.set(r);
                        return g.incrementAndGet();
                    }
                }));
        return map;
    }

    private static void test4() {
        final List<Integer> numbers = Arrays.asList(3, 4, 5, 6, 7, 1, 2, 8, 5, 5, 9, 5, 6, 10, 11, 12);
        final int chunkSize = 10;
        final AtomicInteger counter = new AtomicInteger();
        final AtomicInteger g = new AtomicInteger();
        int a = numbers.stream().collect(Collectors.summingInt(it -> it));
        System.out.println(a);
        Map<Integer, List<Integer>> map = numbers.stream()
                .collect(Collectors.groupingBy(it -> {

                    if (counter.get() + it <= 20) {
                        counter.addAndGet(it);
                        return g.get();
                    } else {
                        counter.set(it);
                        return g.incrementAndGet();
                    }
                }));
        System.out.println(map);

        final AtomicInteger counter2 = new AtomicInteger();
        final Collection<List<Integer>> result = numbers.stream()
                .collect(Collectors.groupingBy(it -> counter2.addAndGet(it) / chunkSize))
                .values();
        System.out.println(result);
    }

    private static void test3() {
        List<Integer> intList = Lists.newArrayList(1, 2, 3, 0, 4, 5, 6, 0, 7, 8);

        int[] indexes =
                Stream.of(IntStream.of(-1), IntStream.range(0, intList.size())
                        .filter(i -> intList.get(i) == 0), IntStream.of(intList.size()))
                        .flatMapToInt(s -> s).toArray();
        System.out.println(Arrays.toString(indexes));
        List<List<Integer>> subSets =
                IntStream.range(0, indexes.length - 1)
                        .mapToObj(i -> intList.subList(indexes[i] + 1, indexes[i + 1]))
                        .collect(Collectors.toList());
        System.out.println(subSets);
    }

    private static void test2() {
        final List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        final int chunkSize = 3;
        final AtomicInteger counter = new AtomicInteger();

        final Collection<List<Integer>> result = numbers.stream()
                .collect(Collectors.groupingBy(it -> counter.getAndIncrement() / chunkSize))
                .values();
        System.out.println(result);
//        Map<Integer, List<Integer>> r2 = numbers.stream()
//                .collect(Collectors.groupingBy(it -> counter.getAndIncrement() / chunkSize));
        final Collection<List<Integer>> result2 = numbers.stream()
                .collect(Collectors.groupingBy(it -> counter.getAndIncrement() % chunkSize))
                .values();
        System.out.println(result2);
        //[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
        //[[3, 6, 9], [1, 4, 7, 10], [2, 5, 8]]
    }

    private static void test1() {
        List<String> ls = Arrays.asList("1,2,3,4,5,6,7,8,9,1,2,4,5,6,7,7,6,6,6,6,6,66".split(","));
        List<List<String>> partition = Lists.partition(ls, 10);

        System.out.println(partition);
        partition.get(0).set(0, "ddd");//改变
        System.out.println(ls);//原数组也变
    }
}
